package cn.miju.ser.framework.response;

import cn.hutool.core.codec.Base64;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import cn.miju.common.content.CodeMessage;
import cn.miju.database.entity.Merchant;
import cn.miju.ser.framework.annotation.DirectResponse;
import cn.miju.ser.framework.constant.SerConstant;
import cn.miju.ser.framework.handler.MiJuContext;
import cn.miju.ser.framework.handler.MiJuContextHandler;
import com.alibaba.fastjson2.JSONObject;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.MethodParameter;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.nio.charset.StandardCharsets;
import java.util.Objects;

/**
 * <pre>
 * 统一结果返回
 * </pre>
 *
 * @author zhuming
 * @version 1.0.0
 * @since 2023-03-01 15:17
 */
@Slf4j
@RequiredArgsConstructor
@RestControllerAdvice(basePackages = {"cn.miju"})
public class ResponseAdvice implements ResponseBodyAdvice<Object> {

    private final StringRedisTemplate redisTemplate;

    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return !returnType.hasMethodAnnotation(DirectResponse.class);
    }

    @SneakyThrows
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        MiJuContext miJuContext = MiJuContextHandler.getMiJuContext();
        MiJuPayResponse miJuPayResponse = null;
        if (Objects.isNull(body)) {
            miJuPayResponse = new MiJuPayResponse(CodeMessage.SUCCESS.getCode(), CodeMessage.SUCCESS.getMessage());
        } else {
            if (body instanceof MiJuPayResponse) {
                //移除上下文
                MiJuContextHandler.removeMiJuContext();
                return body;
            }
            String data = JSONObject.toJSONString(body);
            //加密
            if (miJuContext.isEncryptResponseBody() && StringUtils.isNotBlank(miJuPayResponse.getData())) {
                String merchantInfoKey = SerConstant.Redis.MERCHANT_INFO + miJuContext.getMerchantId();
                Merchant merchant = JSONObject.parseObject(redisTemplate.opsForValue().get(merchantInfoKey), Merchant.class);
                // 私钥加密
                RSA rsa = new RSA(merchant.getPrivateKey(), null);
                byte[] encrypt = rsa.encrypt(data.getBytes(StandardCharsets.UTF_8), KeyType.PrivateKey);
                miJuPayResponse.setData(Base64.encode(encrypt));
            }
            miJuPayResponse = new MiJuPayResponse(CodeMessage.SUCCESS.getCode(), CodeMessage.SUCCESS.getMessage(), data);
        }
        //移除上下文
        MiJuContextHandler.removeMiJuContext();
        return miJuPayResponse;
    }

}
